﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;

namespace GBricks
{
  using System.Diagnostics.Contracts;
  using Properties;

  [DebuggerNonUserCode]
  public static class ExceptionBuilder
  {
    private static string Message([Localizable(true)] string format, params object[] args) {
      Contract.Ensures(Contract.Result<string>() != null);

      if(args == null || args.Length == 0) {
        return format ?? String.Empty;
      }//if

      return String.Format(Resources.Culture, format, args);
    }

    private static string ContinueMessage(string previous, [Localizable(true)] string format, params object[] args) {
      Contract.Ensures(Contract.Result<string>() != null);

      if(String.IsNullOrEmpty(format)) {
        return previous ?? String.Empty;
      }//if

      return previous + Environment.NewLine + Message(format, args);
    }

    public static ArgumentException Argument(string name, [Localizable(true)] string format = null, params object[] args) {
      Contract.Ensures(Contract.Result<Exception>() != null);
      var message = Message(format, args);
      return new ArgumentException(message, name);
    }

    public static ArgumentNullException ArgumentNull(string name, [Localizable(true)] string format = null, params object[] args) {
      Contract.Ensures(Contract.Result<Exception>() != null);
      var message = Message(format, args);
      return new ArgumentNullException(name, message);
    }

    public static Exception ArgumentEmpty(string name, [Localizable(true)] string format = null, params object[] args) {
      Contract.Ensures(Contract.Result<Exception>() != null);
      var message = ContinueMessage(Resources.ArgumentEmpty, format, args);
      return new ArgumentNullException(name, message);
    }

    public static ArgumentOutOfRangeException ArgumentOutOfRange(string name, [Localizable(true)] string format = null, params object[] args) {
      Contract.Ensures(Contract.Result<Exception>() != null);
      var message = Message(format, args);
      return new ArgumentOutOfRangeException(name, message);
    }

    public static ArgumentOutOfRangeException ArgumentOutOfRange(string name, object value, [Localizable(true)] string format = null, params object[] args) {
      Contract.Ensures(Contract.Result<Exception>() != null);
      var message = Message(format, args);
      return new ArgumentOutOfRangeException(name, value, message);
    }

    public static InvalidOperationException InvalidOperation([Localizable(true)] string format = null, params object[] args) {
      Contract.Ensures(Contract.Result<Exception>() != null);
      var message = Message(format, args);
      return new InvalidOperationException(message);
    }

    public static NotSupportedException NotSupported([Localizable(true)] string format = null, params object[] args) {
      Contract.Ensures(Contract.Result<Exception>() != null);
      var message = Message(format, args);
      return new NotSupportedException(message);
    }

    public static KeyNotFoundException KeyNotFound([Localizable(true)] string format = null, params object[] args) {
      Contract.Ensures(Contract.Result<Exception>() != null);
      var message = Message(format, args);
      return new KeyNotFoundException(message);
    }

    public static Exception KeyNotFound<T>(T key) {
      Contract.Ensures(Contract.Result<Exception>() != null);
      var message = String.Format(Resources.Culture, Resources.KeyNotFound1, key);
      return KeyNotFound(message);
    }
  }
}
